Crate bevy_xpbd_3d

source ·
Expand description

§Bevy XPBD

Bevy XPBD is a 2D and 3D physics engine based on Extended Position Based Dynamics (XPBD) for the Bevy game engine.

Check out the GitHub repository for more information about the design, read the Getting started guide below to get up to speed, and take a look at the Table of contents for an overview of the engine’s features and their documentation.

You can also check out the FAQ, and if you encounter any further problems, consider saying hello on the Bevy Discord!

§Getting started

This short guide should help you get started with Bevy XPBD.

§Add the dependency

First, add bevy_xpbd_2d or bevy_xpbd_3d to the dependencies in your Cargo.toml:

# For 2D applications:
[dependencies]
bevy_xpbd_2d = "0.4"

# For 3D applications:
[dependencies]
bevy_xpbd_3d = "0.4"

# If you want to use the most up-to-date version, you can follow the main branch:
[dependencies]
bevy_xpbd_3d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main" }

You can specify features by disabling the default features and manually adding the feature flags you want:

[dependencies]
# Add 3D Bevy XPBD with double-precision floating point numbers.
# `parry-f64` enables collision detection using Parry.
bevy_xpbd_3d = { version = "0.4", default-features = false, features = ["3d", "f64", "parry-f64"] }

§Feature flags

FeatureDescriptionDefault feature
2dEnables 2D physics. Incompatible with 3d.Yes (bevy_xpbd_2d)
3dEnables 3D physics. Incompatible with 2d.Yes (bevy_xpbd_3d)
f32Enables f32 precision for physics. Incompatible with f64.Yes
f64Enables f64 precision for physics. Incompatible with f32.No
default-colliderEnables the default Collider. Required for spatial queries. Requires either the parry-f32 or parry-f64 feature.Yes
parry-f32Enables the f32 version of the Parry collision detection library. Also enables the default-collider feature.Yes
parry-f64Enables the f64 version of the Parry collision detection library. Also enables the default-collider feature.No
collider-from-meshAllows you to create Colliders from Meshes.Yes
async-colliderAllows you to generate Colliders from mesh handles and scenes.Yes
debug-pluginEnables physics debug rendering using the PhysicsDebugPlugin. The plugin must be added separately.Yes
enhanced-determinismEnables increased determinism.No
parallelEnables some extra multithreading, which improves performance for larger simulations but can add some overhead for smaller ones.Yes
simdEnables SIMD optimizations.No
serializeEnables support for serialization and deserialization using Serde.No

§Install the plugin

Bevy XPBD is designed to be very modular. It is built from several plugins that manage different parts of the engine. These plugins can be easily initialized and configured through the PhysicsPlugins plugin group.

use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, PhysicsPlugins::default()))
        // ...your other plugins, systems and resources
        .run();
}

Now you can use all of Bevy XPBD’s components and resources to build whatever you want!

For example, adding a rigid body with a collider is as simple as spawning an entity with the RigidBody and Collider components:

use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;

fn setup(mut commands: Commands) {
    commands.spawn((RigidBody::Dynamic, Collider::sphere(0.5)));
}

You can find lots of usage examples in the project’s repository.

§Table of contents

Below is a structured overview of the documentation for the various features of the engine.

§Rigid bodies

§Collision detection

§Constraints and joints

Joint motors and articulations are not supported yet, but they will be implemented in a future release.

§Spatial queries

§Configuration

§Scheduling

§Architecture

§Frequently asked questions

§How does Bevy XPBD compare to Rapier and bevy_rapier?

Rapier is the biggest and most used physics engine in the Rust ecosystem, and it is currently the most mature and feature-rich option.

bevy_rapier is a great physics integration for Bevy, but it does have several problems:

  • It has to maintain a separate physics world and synchronize a ton of data with Bevy each frame
  • The source code is difficult to inspect, as the vast majority of it is glue code and wrappers for Bevy
  • It has poor docs.rs documentation, and the documentation on rapier.rs is often outdated and missing features
  • It is hard to extend as it’s not very modular or composable in design
  • Overall, it doesn’t have a native ECS-like feel outside of its public API

Bevy XPBD on the other hand is built for Bevy with Bevy, and it uses the ECS for both the internals and the public API. This removes the need for a separate physics world, reduces overhead, and makes the source code much more approachable and easy to inspect for Bevy users.

In part thanks to Bevy’s modular architecture and the ECS, Bevy XPBD is also highly composable, as it consists of several independent plugins and provides lots of options for configuration and extensions, from custom schedules and plugins to custom joints and constraints.

In terms of the physics implementation, Rapier uses an impulse/velocity based solver, while Bevy XPBD uses Extended Position Based Dynamics. On paper, XPBD should be more stable and robust, but it hasn’t been widely adopted in mainstream usage yet.

One of the biggest disadvantages of Bevy XPBD is that it is still very young, so it can have lots of bugs, some missing features, and fewer community resources and third party crates. However, it is growing quite rapidly, and it is already pretty close to feature-parity with Rapier.

At the end of the day, both engines are very solid options. If you are looking for a more mature and tested physics integration, bevy_rapier is the better choice, but if you prefer an engine with less overhead and a more native Bevy integration, consider using Bevy XPBD. Their core APIs are also quite similar, so switching between them should be straightforward.

§Why is nothing happening?

Make sure you have added the PhysicsPlugins plugin group and you have given your rigid bodies a RigidBody component. See the getting started section.

§Why is everything moving so slowly?

If your application is in 2D, you might be using pixels as length units. This will require you to use larger velocities and forces than you would in 3D. Make sure you set Gravity to some larger value as well, because its magnitude is 9.81 by default, which is tiny in pixels.

Bevy XPBD doesn’t have a “physics scale” yet, but it will most likely be added in the future so that it’s possible to define some kind of pixels per meter configuration.

§Why did my rigid body suddenly vanish?

Make sure to give your rigid bodies some mass, either by adding a Collider or a MassPropertiesBundle. If your bodies don’t have any mass, any physical interaction is likely to instantly give them infinite velocity.

Bevy XPBD should automatically print warnings when it detects bodies with an invalid mass or inertia.

§Why is performance so bad?

Make sure you are building your project in release mode using cargo build --release.

You can further optimize builds by setting the number of codegen units in your Cargo.toml to 1, although this will also increase build times.

[profile.release]
codegen-units = 1

Note that Bevy XPBD simply isn’t very optimized yet, and it mostly runs on a single thread for now. This will be addressed in future releases.

§Why does my camera following jitter?

When you write a system that makes the camera follow a physics entity, you might notice some jitter.

To fix this, the system needs to:

  • Run after physics so that it has the up-to-date position of the player.
  • Run before transform propagation so that your changes to the camera’s Transform are written to the camera’s GlobalTransform before the end of the frame.

The following ordering constraints should resolve the issue.

app.add_systems(
    PostUpdate,
    camera_follow_player
        .after(PhysicsSet::Sync)
        .before(TransformSystem::TransformPropagate),
);

§Is there a character controller?

Bevy XPBD does not have a built-in character controller, so if you need one, you will need to implement it yourself. However, third party character controllers like bevy_tnua support Bevy XPBD, and bevy_mod_wanderlust and others are also likely to get Bevy XPBD support soon.

For custom character controllers, you can take a look at the dynamic_character_3d and kinematic_character_3d examples to get started.

§Why are there separate Position and Rotation components?

While Transform can be used for the vast majority of things, Bevy XPBD internally uses separate Position and Rotation components. These are automatically kept in sync by the SyncPlugin.

There are several reasons why the separate components are currently used.

  • Position and rotation should be global from the physics engine’s point of view.
  • Transform scale and shearing can cause issues and rounding errors in physics.
  • Transform hierarchies can be problematic.
  • There is no f64 version of Transform.
  • There is no 2D version of Transform (yet), and having a 2D version can optimize several computations.
  • When position and rotation are separate, we can technically have more systems running in parallel.
  • Only rigid bodies have rotation, particles typically don’t (although we don’t make a distinction yet).

In external projects however, using Position and Rotation is only necessary when you need to manage positions in the SubstepSchedule. Elsewhere, you should be able to use Transform.

There is also a possibility that we will revisit this if/when Bevy has a Transform2d component. Using Transform feels more idiomatic and simple, so it would be nice if it could be used directly as long as we can get around the drawbacks.

§Can the engine be used on servers?

Yes! Networking often requires running the simulation in a specific schedule, and in Bevy XPBD you can set the schedule that runs physics and configure the timestep to whatever you want.

One configuration is to run the client in FixedUpdate, and to use a fixed timestep for Time<Physics> on both the server and the client to make sure the physics simulation is only advanced by one step each time the schedule runs.

Note that while Bevy XPBD should be locally deterministic, it can produce slightly different results on different machines.

§Something else?

Physics engines are very large and Bevy XPBD is young, so stability issues and bugs are to be expected.

If you encounter issues, please consider first taking a look at the issues on GitHub and open a new issue if there already isn’t one regarding your problem.

You can also come and say hello on the Bevy Discord server. There you can find a bevy_xpbd thread on the crate-help channel where you can ask questions.

§What is XPBD?

XPBD or Extended Position Based Dynamics is a physics simulation method that extends the traditional PBD to be more physically accurate and less dependent on time step size and iteration count.

Unlike force or impulse based physics simulation methods, XPBD mostly operates at the position-level, which can produce more stable and reliable results, while allowing straightforward coupling of rigid bodies, soft bodies and fluids.

§Simulation loop

At a high level, XPBD consists of a broad phase followed by a substepping loop that handles position integration, constraint solving, velocity updates, and a velocity solver that handles dynamic friction and restitution.

It looks roughly like this:

while simulating:
    // Substep size
    h = ∆t / substep_count

    // Broad phase
    broad_collision_pairs = collect_collision_pairs()

    for substep_count:
        // Integrate
        for n particles and bodies:
            // Integrate position
            x_prev = x
            v = v + h * f_ext / m
            x = x + h * v

            // Integrate rotation
            q_prev = q
            ω = ω + h * I^-1 * (τ_ext - (ω x (I * ω)))
            q = q + h * 0.5 * [ω_x, ω_y, ω_z, 0] * q
            q = q / |q|

        // Narrow phase
        for pair in broad_collision_pairs:
            compute_contacts(pair)

        // Solve constraints (contacts, joints etc.)
        solve_constraints(particles and bodies)

        // Update velocities
        for n particles and bodies:
            v = (x - x_prev) / h
            ∆q = q * q_prev^-1
            ω = 2 * [∆q_x, ∆q_y, ∆q_z] / h
            ω = ∆q_w >= 0 ? ω : -ω

        // Solve velocity constraints (dynamic friction and restitution)
        solve_velocities(particles and bodies)

where h is the substep size, q is the rotation as a quaternion, ω is the angular velocity, I is the angular inertia tensor and τ is the external torque.

In Bevy XPBD, the simulation loop is handled by various plugins. The PhysicsSetupPlugin sets up the Bevy schedules12 and sets345, the BroadPhasePlugin manages the broad phase, the IntegratorPlugin handles XPBD integration, and so on. You can find all of the plugins and their responsibilities here.

§See also

§Learning resources

If you want to learn more about XPBD, I recommend taking a look at some of the papers. Especially the first one from 2020 was used heavily for the simulation loop and constraints in Bevy XPBD.

The papers are quite academic, so you might instead prefer some videos and articles. The first one by Ten Minute Physics (Matthias Müller, one of the XPBD researchers) is great for understanding how XPBD differs from other simulation methods and how the constraints work.

§License

Bevy XPBD is free and open source. All code in the Bevy XPBD repository is dual-licensed under either:

at your option.

Re-exports§

Modules§

  • Commonly used components.
  • Contains constraints used by the solver.
  • Math types and traits used in the crate. Most of the math types are feature-dependent, so they will be different for 2d/3d and f32/f64.
  • The building blocks of Bevy XPBD.
  • Re-exports common components, bundles, resources, plugins and types.
  • Resources used in the simulation.

Structs§

Enums§

  • High-level system sets for the main phases of the physics engine. You can use these to schedule your own systems before or after physics is run without having to worry about implementation details.
  • System sets for the main steps in the physics simulation loop. These are typically run in the PhysicsSchedule.
  • System sets for the the steps in the inner substepping loop. These are typically run in the SubstepSchedule.